12.5.4 コンテキストを使ったゴルーチンの終了
ゴルーチンリークを解消するよくある方法としてコンテキストを使う方法がある
code:go
package main
import (
"context"
"fmt"
)
func countTo(ctx context.Context, max int) <-chan int {
ch := make(chan int)
go func() {
defer close(ch) // ④チャネルをクローズする
for i := 0; i < max; i++ {
select {
case <-ctx.Done(): // ③ctx.Done()が返すチャネルから読み込めた場合
return // ゴルーチンを抜ける
case ch <- i: // iをチャネルchに書き込む
}
}
}()
return ch // chを戻してcountToは終了。途中で呼び出したゴルーチンは実行を続ける
}
func main() {
ctx, cancel := context.WithCancel(context.Background())
// コンテキストを初期化。コンテキストとキャンセルするための関数を返す
defer cancel() // ②処理が終わったらキャンセルを呼び出す
ch := countTo(ctx, 10)
for i := range ch {
if i > 5 {
break // ①breakすると、deferされていたcancel()が実行される
}
fmt.Println(i)
}
}